package net.disy.cadenza.repository.wrappers;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.disy.cadenza.repository.selector.ResultObjectTypes;
import net.disy.cadenza.schema.selection.Condition;
import net.disy.cadenza.schema.selection.ConditionAttribute;
import net.disy.cadenza.schema.selection.Contains;

public class ParameterizedSelectorWrapper {
	private SelectorWrapper selector;
	private Map<String, Set<String>> attributeParameterMap = new HashMap<String, Set<String>>();
	private Map<String, String> keywordToObjectAttribute = new HashMap<String, String>();
	private Set<SelectorCondition> selectorConditions = new HashSet<SelectorCondition>();
	private final String CONDITION_ID_TEMPLATE = "Show.RepositoryItem.Condition(%s).Id=%s&";
	private final String CONDITION_ATTRIBUTE_TEMPLATE = "Show.RepositoryItem.Condition(%s).Attribute(%s)=%s&";
	private final String CONDITION_ATTRIBUTE_VALUE_TEMPLATE = "Show.RepositoryItem.Condition(%s).Row(%s).Value(%s)='%s'&";
	
	
	public ParameterizedSelectorWrapper(SelectorWrapper selector, ResultObjectTypes resultObjectTypes){
		this.selector = selector;
		setParameters(resultObjectTypes);
	}

	public String getName(){
		return selector.getName();
	}
	private void setParameters(ResultObjectTypes resultObjectTypes){
		this.attributeParameterMap.clear();
		this.keywordToObjectAttribute.clear();
		Map<String, Contains> containsConditions = selector.getContainsConditions();
		for(String conditionName : containsConditions.keySet()){
			Contains contains = containsConditions.get(conditionName);
			Condition containsCondition = contains.getCondition();
			SelectorCondition selectorCondition = new SelectorCondition(containsCondition.getConditionObjectType().getObjectTypePath(),  conditionName);
			selectorCondition.setConditionPrintName(containsCondition.getPrintName());
			for(ConditionAttribute conditionAttribute : containsCondition.getConditionAttribute()){
				String attributeName = conditionAttribute.getAttributeName();
				List<String> attributeValues = resultObjectTypes.getObjectAttributeToValues().get(attributeName);
				if(attributeValues != null){
					for(int rowId = 0; rowId < attributeValues.size(); rowId++){
						DefaultConditionValue defautlConditionValue = new DefaultConditionValue();
						int conditionAttributePosition = 0;
						for(ConditionAttribute conditionAttributeParam : containsCondition.getConditionAttribute()){
							String attributeNameParam = conditionAttributeParam.getAttributeName();
							List<String> objectAttributeValues = resultObjectTypes.getObjectAttributeToValues().get(attributeNameParam);
							if(objectAttributeValues != null){
								String conditionAttributeValue = objectAttributeValues.get(rowId);
								defautlConditionValue.addAttributeValue(attributeNameParam, conditionAttributeValue);
								if(conditionAttributePosition == 0)
									defautlConditionValue.setMainAttributeName(attributeNameParam);
								Set<String> parametersForAttribute = attributeParameterMap.get(attributeNameParam);
								if(parametersForAttribute == null){
									parametersForAttribute = new HashSet<String>();
									attributeParameterMap.put(attributeNameParam, parametersForAttribute);
								}
								parametersForAttribute.add(conditionAttributeValue);
								for(String keyword : resultObjectTypes.getKeywordToObjectAttributes().keySet()){
									Set<String> objectAttributesToKeyword = resultObjectTypes.getKeywordToObjectAttributes().get(keyword);
									if(objectAttributesToKeyword.contains(attributeNameParam))
										keywordToObjectAttribute.put(keyword, attributeNameParam);
								}
							}
							conditionAttributePosition++;
						}
						if(defautlConditionValue.getAttributeValues().size() != 0){
							selectorCondition.addDefaultValue(defautlConditionValue);
						}
					}
					break;
				}
				
			}
			if(selectorCondition.getDefaultValues() != null && selectorCondition.getDefaultValues().size() != 0){
				selectorConditions.add(selectorCondition);
			}
		}
	}
	
	public String getURL(){
		StringBuffer url = new StringBuffer("");
		int conditionId = 0;
		for(SelectorCondition selectorCondition : getSelectorConditions()){
			if(selectorCondition.hasEnabledDefaultValue()){
				String conditionName = selectorCondition.getConditionName();
				StringBuffer attributesForCondition = new StringBuffer();
				StringBuffer attributeValuesForCondition = new StringBuffer();
				attributesForCondition.append(String.format(CONDITION_ID_TEMPLATE, conditionId, conditionName + ".cnd"));
				int attributeId = 0;
				int rowId = 0;
				for(DefaultConditionValue defaultConditionValue : selectorCondition.getDefaultValues()){
					if(attributeId == 0){
						for(String attributeName : defaultConditionValue.getAttributeValues().keySet()){
							attributesForCondition.append(String.format(CONDITION_ATTRIBUTE_TEMPLATE, conditionId, attributeId, attributeName));
							attributeId++;
						}
					}
					Map<String, String> attributeValues = defaultConditionValue.getAttributeValues();
					int valueId = 0;
					for(String attributeName : attributeValues.keySet()){
						String attributeValue = attributeValues.get(attributeName);
						attributeValuesForCondition.append(String.format(CONDITION_ATTRIBUTE_VALUE_TEMPLATE, conditionId, rowId, valueId, attributeValue));
						valueId++;
					}
					rowId++;
				}
				url.append(attributesForCondition).append(attributeValuesForCondition);
				conditionId++;
			}
		}
		if(url.toString() != "")
			url.deleteCharAt(url.length() - 1);
		return url.toString();
	}

	public Set<SelectorCondition> getSelectorConditions() {
		return selectorConditions;
	}

	public boolean areSelectorConditionsContained(Set<SelectorCondition> otherWorkflowConditions){
		for(SelectorCondition selectorCondition : this.selectorConditions){
			boolean existEqualCondition = false;
			for(SelectorCondition otherSelectorCondition : otherWorkflowConditions){
				if(selectorCondition.equalTo(otherSelectorCondition)){
					existEqualCondition = true;
					break;
				}
			}
			if(!existEqualCondition)
				return false;
		}
		return true;
	}
}
